﻿using Microsoft.Xrm.Sdk;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Shapes;
using System.Windows.Forms;
using System.Windows.Forms.Integration;
using System.Drawing;
using Microsoft.Xrm.Sdk.Query;

namespace Email_Validator
{
    /// <summary>
    /// Interaction logic for DiagnosticWindow.xaml
    /// </summary>
    public partial class DiagnosticWindow : Window
    {
        private Entity _organizationSettings;

        public Entity OrganizationSettings
        {
            get { return _organizationSettings; }
            set { _organizationSettings = value; }
        }

        private Entity _mailbox;

        public Entity Mailbox
        {
            get { return _mailbox; }
            set { _mailbox = value; }
        }

        private Entity _queue;

        public Entity Queue
        {
            get { return _queue; }
            set { _queue = value; }
        }

        private Entity _userSetting;

        public Entity UserSetting
        {
            get { return _userSetting; }
            set { _userSetting = value; }
        }

        private Entity _emailServerProfile;

        public Entity EmailServerProfile
        {
            get { return _emailServerProfile; }
            set { _emailServerProfile = value; }
        }

        private crmauthinfo _crmAuth;

        public crmauthinfo CrmAuth
        {
            get { return _crmAuth; }
            set { _crmAuth = value; }
        }

        public exchangeauthinfo ExchangeAuth
         {
            get { return _exchangeAuth; }
            set { _exchangeAuth = value; }
        }

        private exchangeauthinfo _exchangeAuth;

        public ImageList ListImages
        {
            get { return _listImages; }
            set { _listImages = value; }
        }

        private ImageList _listImages;

        public bool OrgError = false;
        public bool OrgWarning = false;
        public bool MailboxError = false;
        public bool MailboxWarning = false;
        public bool MiscError = false;
        public bool MiscWarning = false;
        public bool MailboxUsingSSS = false;
        public bool MailboxUsingOutlook = false;
        public bool MailboxUsingRouter = false;
        public bool MailboxApproved = false;
       

        public DiagnosticWindow(Entity orgsettings, Entity mailbox, Entity queue, Entity usersettings, Entity emailserverprofile, crmauthinfo crmauth, exchangeauthinfo exchangeauth)
        {
            _organizationSettings = orgsettings;
            _mailbox = mailbox;
            if (queue != null)
            {
                _queue = queue;
            }
            if (usersettings != null)
            {
                _userSetting = usersettings;
            }
            if (emailserverprofile != null)
            {
                _emailServerProfile = emailserverprofile;
            }
            _crmAuth = crmauth;
            _exchangeAuth = exchangeauth;
            ListImages = new ImageList();
            InitializeImageList();
            InitializeComponent();
          
        }

        private void InitializeImageList()
        {
            ListImages.Images.Add(System.Drawing.Image.FromFile(@"Images\GreenCheck.png"));
            ListImages.Images.Add(System.Drawing.Image.FromFile(@"Images\warning.png"));
            ListImages.Images.Add(System.Drawing.Image.FromFile(@"Images\error.png"));
            ListImages.Images.Add(System.Drawing.Image.FromFile(@"Images\information.png"));
        }

        private void BuildTree(object sender)
        {
            diagnosticTree.ImageList = ListImages;
            SetTreeProperties();
            BuildOrganization(sender);
            BuildMailbox(sender);
            BuildMisc(sender);
            SetHeaders();

            
        }

        private void SetTreeProperties()
        {
            if (((OptionSetValue)OrganizationSettings["emailconnectionchannel"]).Value == 0 && ((OptionSetValue)Mailbox["incomingemaildeliverymethod"]).Value == 2 || ((OptionSetValue)Mailbox["incomingemaildeliverymethod"]).Value == 3)
            {
                MailboxUsingSSS = true;
            }
            if (((OptionSetValue)Mailbox["incomingemaildeliverymethod"]).Value == 1)
            {
                MailboxUsingOutlook = true;
            }
            if (((OptionSetValue)OrganizationSettings["emailconnectionchannel"]).Value == 1 && ((OptionSetValue)Mailbox["incomingemaildeliverymethod"]).Value == 2 || ((OptionSetValue)Mailbox["incomingemaildeliverymethod"]).Value == 3)
            {
                MailboxUsingRouter = true;
            }
            if (((OptionSetValue)Mailbox["emailrouteraccessapproval"]).Value == 1)
            {
                MailboxApproved = true;
            }
        }

        private void SetHeaders()
        {
            if (OrgError)
            {
                diagnosticTree.Nodes[0].ImageIndex = 2;
                diagnosticTree.Nodes[0].SelectedImageIndex = 2;
            }
            else if (OrgWarning)
            {
                diagnosticTree.Nodes[0].ImageIndex = 1;
                diagnosticTree.Nodes[0].SelectedImageIndex = 1;
            }

            if (MailboxError)
            {
                diagnosticTree.Nodes[1].ImageIndex = 2;
                diagnosticTree.Nodes[1].SelectedImageIndex = 2;
                diagnosticTree.Nodes[1].Nodes[0].ImageIndex = 2;
                diagnosticTree.Nodes[1].Nodes[0].SelectedImageIndex = 2;
            }

            else if (MailboxWarning)
            {
                diagnosticTree.Nodes[1].ImageIndex = 1;
                diagnosticTree.Nodes[1].SelectedImageIndex = 1;
                diagnosticTree.Nodes[1].Nodes[0].ImageIndex = 1;
                diagnosticTree.Nodes[1].Nodes[0].SelectedImageIndex = 1;
            }

            if (MiscError)
            {
                diagnosticTree.Nodes[2].ImageIndex = 2;
                diagnosticTree.Nodes[2].SelectedImageIndex = 2;
            }
            else if (MiscWarning)
            {
                diagnosticTree.Nodes[2].ImageIndex = 1;
                diagnosticTree.Nodes[2].SelectedImageIndex = 1;
            }

        }

        private void BuildMisc(object sender)
        {
            TreeNode header = new TreeNode("Miscellaneous");
            diagnosticTree.Nodes.Add(header);

            if (MailboxUsingOutlook)
            {
                diagnosticTree.Nodes[2].Nodes.Add("Incoming Email Delivery Method is set to Outlook");
                DetermineOutlookPromotion();
                diagnosticTree.Nodes[2].Nodes.Add("Email Tagging is Disabled in CRM 2015+");
                DetermineEmailTagging();
                diagnosticTree.Nodes[2].Nodes.Add("Duplicate E-mail Addresses Found in CRM");
                DetermineDuplicateEmailAddresses();
            }
            else
            {
                diagnosticTree.Nodes[2].Nodes.Add("Duplicate E-mail Addresses Found in CRM");
                DetermineDuplicateEmailAddresses();
            }
        }

        private void DetermineDuplicateEmailAddresses()
        {
            bool multipleemails = RetrieveMailboxesbyEmail();

            if (MailboxUsingSSS)
            {
                if (multipleemails)
                {
                    diagnosticTree.Nodes[2].Nodes[0].ImageIndex = 2;
                    diagnosticTree.Nodes[2].Nodes[0].SelectedImageIndex = 2;
                    diagnosticTree.Nodes[2].Nodes[0].ToolTipText = "Multiple e-mail addresses were found. This can cause duplicate e-mail activity party members in CRM during email address resolution.";
                    MiscError = true;
                }
                else
                {
                    diagnosticTree.Nodes[2].Nodes[0].ImageIndex = 0;
                    diagnosticTree.Nodes[2].Nodes[0].SelectedImageIndex = 0;
                }
            }
            else
            {
                if (multipleemails)
                {
                    diagnosticTree.Nodes[2].Nodes[2].ImageIndex = 2;
                    diagnosticTree.Nodes[2].Nodes[2].SelectedImageIndex = 2;
                    diagnosticTree.Nodes[2].Nodes[2].ToolTipText = "Multiple e-mail addresses were found. This can cause duplicate e-mail activity party members in CRM during email address resolution.";
                    MiscError = true;
                }
                else
                {
                    diagnosticTree.Nodes[2].Nodes[0].ImageIndex = 0;
                    diagnosticTree.Nodes[2].Nodes[0].SelectedImageIndex = 0;
                }
            }
        }

        private bool RetrieveMailboxesbyEmail()
        {
            try {

                bool duplicatefound;

                QueryByAttribute query = new QueryByAttribute("mailbox");
                query.ColumnSet = new ColumnSet();
                query.Attributes.AddRange("emailaddress");
                query.Values.AddRange((string)Mailbox["emailaddress"]);
                query.Attributes.AddRange("statecode");
                query.Values.AddRange(0);

                EntityCollection mailboxes = CrmAuth.CrmService.RetrieveMultiple(query);

                if (mailboxes.Entities.Count == 1)
                {
                    duplicatefound = false;
                    return duplicatefound;
                }
                else
                {
                    duplicatefound = true;
                    return duplicatefound;
                }
            }
            catch (Exception e)
            {
                System.Windows.MessageBox.Show(MainWindow.GetErrorDetail(e), "Exception during Mailbox Retrieve");
                bool error = true;
                return error;
            }
        }

        private void DetermineEmailTagging()
        {
            diagnosticTree.Nodes[2].Nodes[1].ImageIndex = 1;
            diagnosticTree.Nodes[2].Nodes[1].SelectedImageIndex = 1;
            diagnosticTree.Nodes[2].Nodes[1].ToolTipText = "E-mail Tagging is disabled by default in CRM 2015 and later versions. This can cause e-mails tracked by other users or queues to appear as untracked in Outlook.";
            MiscWarning = true;
        }

        private void DetermineOutlookPromotion()
        {
            diagnosticTree.Nodes[2].Nodes[0].ImageIndex = 1;
            diagnosticTree.Nodes[2].Nodes[0].SelectedImageIndex = 1;
            diagnosticTree.Nodes[2].Nodes[0].ToolTipText = "Emails will only be tracked into CRM when Outlook is running and the user has enabled Automatic Tracking (BackgroundReceive) via their Personal Options.";
            MiscWarning = true;
        }

        private void BuildMailbox(object sender)
        {
            TreeNode header = new TreeNode("User & Mailbox Settings");
            diagnosticTree.Nodes.Add(header);

            if (MailboxUsingSSS)
            {
                diagnosticTree.Nodes[1].Nodes.Add("Server Side Synchronization Diagnostics");
                diagnosticTree.Nodes[1].Nodes[0].Nodes.Add("Incoming Email Status");
                DetermineIncomingEmailStatus();
                diagnosticTree.Nodes[1].Nodes[0].Nodes.Add("Enabled For Incoming");
                DetermineEnabledForIncoming();
                diagnosticTree.Nodes[1].Nodes[0].Nodes.Add("Mailbox Processing Stalled");
                DetermineStuckMailbox();
                diagnosticTree.Nodes[1].Nodes[0].Nodes.Add("Org Marked As Primary For Synchronization");
                DeterminePrimaryOrg();
                diagnosticTree.Nodes[1].Nodes[0].Nodes.Add("Latency in Mailbox Processing");
                DetermineReceivingPostPonedUntil();
                diagnosticTree.Nodes[1].Nodes[0].Nodes.Add("Incoming Delivery Method");
                DetermineIncomingDeliveryMethod();
                diagnosticTree.Nodes[1].Nodes[0].Nodes.Add("Email Address Match");
                DetermineEmailAddress();
                diagnosticTree.Nodes[1].Nodes[0].Nodes.Add("Email Address Approval");
                DetermineEmailApproval();

            }
            else if (MailboxUsingRouter)
            {
                diagnosticTree.Nodes[1].Nodes.Add("E-mail Router Mailbox Diagnostics");
                diagnosticTree.Nodes[1].Nodes[0].Nodes.Add("Incoming Delivery Method");
                DetermineIncomingDeliveryMethod();
                diagnosticTree.Nodes[1].Nodes[0].Nodes.Add("Email Address Match");
                DetermineEmailAddress();
                diagnosticTree.Nodes[1].Nodes[0].Nodes.Add("Email Address Approval");
                DetermineEmailApproval();
            }

            else
            {
                diagnosticTree.Nodes[1].Nodes.Add("General Mailbox Diagnostics");
                diagnosticTree.Nodes[1].Nodes[0].Nodes.Add("Incoming Delivery Method");
                DetermineIncomingDeliveryMethod();
                diagnosticTree.Nodes[1].Nodes[0].Nodes.Add("Email Address Match");
                DetermineEmailAddress();
                diagnosticTree.Nodes[1].Nodes[0].Nodes.Add("Email Address Approval");
                DetermineEmailApproval();
            }
        }

        private void DetermineEmailApproval()
        {
            TreeNode node = GetCurrentMailboxNode();

            if (!MailboxApproved)
            {
                node.ImageIndex = 2;
                node.SelectedImageIndex = 2;
                node.ToolTipText = "The mailbox must be approved by a System Administrator before e-mail processing can occur.";
                MailboxError = true;
            }
        }

        private TreeNode GetCurrentMailboxNode()
        {
            int length = diagnosticTree.Nodes[1].Nodes[0].Nodes.Count - 1;
            TreeNode node = diagnosticTree.Nodes[1].Nodes[0].Nodes[length];
            return node;
        }

        private void DetermineEmailAddress()
        {
            //Exchange Online w/ no impersonation
            if (!ExchangeAuth.Impersonate && ExchangeAuth.ExchangeOnline && ExchangeAuth.UserName != (string)Mailbox["emailaddress"])
            {
                TreeNode node = GetCurrentMailboxNode();
                node.ImageIndex = 2;
                node.SelectedImageIndex = 2;
                node.ToolTipText = "The e-mail address of the mailbox record in CRM does not match the Exchange e-mail address that was provided.";
                MailboxError = true;
            }

            //Exchange Impersonation
            if (ExchangeAuth.Impersonate && ExchangeAuth.SmtpAddress != (string)Mailbox["emailaddress"])
            {
                TreeNode node = GetCurrentMailboxNode();
                node.ImageIndex = 2;
                node.SelectedImageIndex = 2;
                node.ToolTipText = "The e-mail address of the mailbox record in CRM does not match the Exchange e-mail address that was provided.";
                MailboxError = true;
            }

            //To-Do: Add Exchange On Premise w/ no impersonation
        }

        private void DetermineIncomingDeliveryMethod()
        {
            if (((OptionSetValue)Mailbox["incomingemaildeliverymethod"]).Value == 0)
            {
                TreeNode node = GetCurrentMailboxNode();
                node.ImageIndex = 2;
                node.SelectedImageIndex = 2;
                node.ToolTipText = "The mailbox is currently not configured to automatically promote email. Open the mailbox and select an Incoming Email Delivery method.";
                MailboxError = true;
            }
        }

        private void DetermineReceivingPostPonedUntil()
        {
            DateTime date = new DateTime();
            date = DateTime.UtcNow;
            if ((DateTime)Mailbox["receivingpostponeduntil"] > date.Add(new TimeSpan(0, 12, 0, 0)))
            {
                diagnosticTree.Nodes[1].Nodes[0].Nodes[4].ImageIndex = 1;
                diagnosticTree.Nodes[1].Nodes[0].Nodes[4].SelectedImageIndex = 1;
                diagnosticTree.Nodes[1].Nodes[0].Nodes[4].ToolTipText = "Mailbox processing is postponed beyond 12 hours from the current time.";
                MailboxWarning = true;
            }
        }

        private void DeterminePrimaryOrg()
        {
            if (!(bool)Mailbox["orgmarkedasprimaryforexchangesync"])
            {
                diagnosticTree.Nodes[1].Nodes[0].Nodes[3].ImageIndex = 1;
                diagnosticTree.Nodes[1].Nodes[0].Nodes[3].SelectedImageIndex = 1;
                MailboxWarning = true;
                diagnosticTree.Nodes[1].Nodes[0].Nodes[3].ToolTipText = "The configured organization is not the primary organization for Server Side Synchronization for the target mailbox. To set this, Test & Enable the mailbox and ensure Marked As Primary is checked.";
            }
        }

        private void DetermineStuckMailbox()
        {
            if (((DateTime)Mailbox["postponemailboxprocessinguntil"]).Date == DateTime.MaxValue.Date && (int)Mailbox["processingstatecode"] == 0)
            {
                diagnosticTree.Nodes[1].Nodes[0].Nodes[2].ImageIndex = 2;
                diagnosticTree.Nodes[1].Nodes[0].Nodes[2].SelectedImageIndex = 2;
                diagnosticTree.Nodes[1].Nodes[0].Nodes[2].ToolTipText = "The mailbox is not currently processing e-mail and is considered inactive. The mailbox may have encountered an error during processing. Check the mailbox alerts and server traces for more information.";
                MailboxError = true;
            }
        }

        private void DetermineEnabledForIncoming()
        {
            if (!(bool)Mailbox["enabledforincomingemail"])
            {
                diagnosticTree.Nodes[1].Nodes[0].Nodes[1].ImageIndex = 2;
                diagnosticTree.Nodes[1].Nodes[0].Nodes[1].SelectedImageIndex = 2;
                diagnosticTree.Nodes[1].Nodes[0].Nodes[1].ToolTipText = "The mailbox is not currently enabled for Incoming Email Processing. A System Administrator will need to Approve and  Test & Enable the mailbox.";
                MailboxError = true;
            }
        }

        private void DetermineIncomingEmailStatus()
        {
            if (((OptionSetValue)Mailbox["incomingemailstatus"]).Value == 0 || ((OptionSetValue)Mailbox["incomingemailstatus"]).Value == 2)
            {
                diagnosticTree.Nodes[1].Nodes[0].Nodes[0].ImageIndex = 2;
                diagnosticTree.Nodes[1].Nodes[0].Nodes[0].SelectedImageIndex = 2;
                if (((OptionSetValue)Mailbox["incomingemailstatus"]).Value == 0)
                {
                    diagnosticTree.Nodes[1].Nodes[0].Nodes[0].ToolTipText = "The mailbox has not been Tested and Enabled by a System Administrator.";
                }
                else
                {
                    diagnosticTree.Nodes[1].Nodes[0].Nodes[0].ToolTipText = "The mailbox failed Test Access. Please check the mailbox alerts and server traces for more information.";
                }
                    MailboxError = true;
            }
        }

        private void BuildOrganization(object sender)
        {
            TreeNode header = new TreeNode("Organization Settings");
            diagnosticTree.Nodes.Add(header);
            diagnosticTree.Nodes[0].Nodes.Add("Ignore Internal Email");
            DetermineInternalEmail();
            diagnosticTree.Nodes[0].Nodes.Add("Connection Channel");
            DetermineConnectionChannel();
            diagnosticTree.Nodes[0].Nodes.Add("E-mail Correlation Enabled");
            DetermineCorrelationEnabled();
            diagnosticTree.Nodes[0].Nodes.Add("OrgDBOrgSettings");
            DetermineOrgDBOrgSettings();
            diagnosticTree.Nodes[0].Nodes.Add("Tracking Token & Smart Matching Settings");
            DetermineCorrelationMethods();
        }

        private void DetermineCorrelationMethods()
        {
            if ((int)OrganizationSettings["maximumtrackingnumber"] == 0 && !OrganizationSettings.Contains("enablesmartmatching"))
            {
                diagnosticTree.Nodes[0].Nodes[4].ImageIndex = 1;
                diagnosticTree.Nodes[0].Nodes[4].SelectedImageIndex = 1;
                diagnosticTree.Nodes[0].Nodes[4].ToolTipText = "Both tracking token and Smart Matching are disabled. This will inhibit CRM from ensuring that tracked email responses are correctly tracked for users or queues that are set to promote e-mail in response to CRM e-mail.";
                OrgWarning = true;
            }
        }

        private void DetermineOrgDBOrgSettings()
        {
            //To-Do: Parse OrgDBOrgSettings and display as child nodes.
            diagnosticTree.Nodes[0].Nodes[3].ImageIndex = 3;
            diagnosticTree.Nodes[0].Nodes[3].SelectedImageIndex = 3;
            if (OrganizationSettings.Contains("orgdborgsettings"))
            {
                diagnosticTree.Nodes[0].Nodes[3].ToolTipText = (string)OrganizationSettings["orgdborgsettings"];
            }
            else
            {
                diagnosticTree.Nodes[0].Nodes[3].ToolTipText = "No OrgDBOrgSettings have been implemented";
            }
        }

        private void DetermineCorrelationEnabled()
        {
            if (!(bool)OrganizationSettings["emailcorrelationenabled"])
            {
                diagnosticTree.Nodes[0].Nodes[2].ImageIndex = 1;
                diagnosticTree.Nodes[0].Nodes[2].SelectedImageIndex = 1;
                diagnosticTree.Nodes[0].Nodes[2].ToolTipText = "E-mail Correlation allows Server Side Sync to utilize In-Reply-To and ConversationIndex message headers to provide greater flexibility when correlating e-mail messages in response to CRM e-mail. Disabling this setting is not recommended.";
                OrgWarning = true;
            }
        }

        private void DetermineConnectionChannel()
        {
            diagnosticTree.Nodes[0].Nodes[1].ImageIndex = 3;
            diagnosticTree.Nodes[0].Nodes[1].SelectedImageIndex = 3;
            string connectionchanneltext = ValidatorWindow.GetOptionSetValueLabel("organization", "emailconnectionchannel", ((OptionSetValue)OrganizationSettings["emailconnectionchannel"]).Value, CrmAuth.CrmService);
            diagnosticTree.Nodes[0].Nodes[1].ToolTipText = connectionchanneltext;
            return;
        }

        private void DetermineInternalEmail()
        {
            if ((bool)OrganizationSettings["ignoreinternalemail"])
            {
                diagnosticTree.Nodes[0].Nodes[0].ImageIndex = 1;
                diagnosticTree.Nodes[0].Nodes[0].SelectedImageIndex = 1;
                diagnosticTree.Nodes[0].Nodes[0].ToolTipText = "E-mails will not track automatically between CRM users. This setting can be changed in the System Settings.";
                ToolTip = true;
            }
           
        }

        private void Window_Loaded(object sender, RoutedEventArgs e)
        {
            BuildTree(sender);
        }


        private void diagnosticTree_NodeMouseClick(object sender, TreeNodeMouseClickEventArgs e)
        {
          
            if (e.Node == diagnosticTree.Nodes[0] || e.Node == diagnosticTree.Nodes[1] || e.Node == diagnosticTree.Nodes[2])
            {
                txtBoxDescription.Text = "Select a child node to view more information";
                
            }
            else
            {
                txtBoxDescription.Text = e.Node.ToolTipText;
            }

        }
    }
}
